﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using FMOD;

namespace Rockfan.Framework.Audio
{
    internal static class AudioEngine
    {
        // TODO GET CURRENT SYSTEM AUDIO VOLUME, 
        // ON SOUND CREATION, SET SOUND LEVEL TO CURRENT AUDIO LEVEL
        // UPDATE ALL SOUNDS TO USE NEW AUDIO LEVEL, ON SYSTEM AUDIO LEVEL CHANGE

        static AudioEngine()
        {
            Sounds = new List<ISound>();

            FMOD.Factory.System_Create(ref System);
            System.init(50, INITFLAGS.NORMAL , (IntPtr)null);
        }

        public static FMOD.Sound CreateSound(string fileLocation, bool isLooped)
        {
            var flags = MODE.HARDWARE | MODE.ACCURATETIME | MODE.CREATESAMPLE | MODE._2D;

            if (isLooped)
                flags |= MODE.LOOP_NORMAL;

            var sound = default(Sound);
            LastError = System.createSound(fileLocation, flags, ref sound);

            // if ok to continue, do so, otherwise what's the point of setting more values
            if (LastError == RESULT.OK)
                LastError = System.setSpeakerMode(SPEAKERMODE.MAX);

            return sound;
        }

        public static DSP CreateDSP(DSP_TYPE type)
        {
            var dsp = default(DSP);
            LastError = System.createDSPByType(type, ref dsp);
            
            return dsp;
        }

        public static void PlaySound(Sound sound, ref Channel channel)
        {
            System.playSound(CHANNELINDEX.FREE, sound, true, ref channel);
        }

        public static void AddSound(ISound sound)
        {
            if (!Sounds.Contains(sound))
                Sounds.Add(sound);
        }

        public static void Remove(ISound sound)
        {
            while (Sounds.Contains(sound))
                Sounds.Remove(sound);
        }
        
        public static void Update(float delta)
        {
            System.update();

            foreach (var sound in Sounds)
                sound.Update(delta);
        }

        public static FMOD.RESULT GetLastError() { return RESULT.OK; }

        private static FMOD.System System;
        private static RESULT LastError;

        private static List<ISound> Sounds;
    }
}
